﻿using System;
using System.Collections.Generic;

using System.Text;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace RemoteGacutil.Logic
{
    public class GacUtil
    {
        private string gacUtil = Path.Combine(Application.StartupPath, "gacutil.exe");
        private Regex asmListRegex = new Regex(@"(?<name>[\w.]+),\sVersion=(?<ver>[\w.]+),\sCulture=(?<cul>[\w.]+),\sPublicKeyToken=(?<pubkey>[\w]+)(?:,\sprocessorArchitecture=(?<proc>[\w]+))?", RegexOptions.Compiled);
        private string server;

        public GacUtil(string server)
        {
            this.server = server;
        }

        private string ExecGacutil(string args)
        {
            if(server.Equals("localhost"))
                return PsExecUtil.LocalExecute(gacUtil, args);
            else
                return PsExecUtil.Execute(server, "-c " + gacUtil, args);
        }

        public List<CachedAssembly> GetCachedAssemblies()
        {
            string result = ExecGacutil("/l");
            List<CachedAssembly> list = new List<CachedAssembly>();
            if (!string.IsNullOrEmpty(result))
            {
                foreach (Match match in asmListRegex.Matches(result))
	            {
                    CachedAssembly asm = new CachedAssembly();
                    asm.AssemblyName = match.Groups["name"].Value;
                    asm.Version = match.Groups["ver"].Value;
                    asm.PublicKeyToken = match.Groups["pubkey"].Value;
                    asm.Culture = match.Groups["cul"].Value;
                    asm.CacheEntry = match.Value;
                    list.Add(asm);
	            } 
            }
            return list;
        }

        public void Install(string assemblyPath)
        {
            string asmFileName = Path.GetFileName(assemblyPath);
            string remotePath = string.Format(@"\\{0}\ADMIN$\{1}", server, asmFileName);
            string path = @"C:\Windows\" + asmFileName;
            File.Copy(assemblyPath, remotePath, true);
            File.SetAttributes(remotePath, FileAttributes.Normal);
            string result = ExecGacutil(string.Format(@"/i ""{0}"" /f", path));
            if (result.IndexOf("successfully added")<0)
            {
                throw new Exception("Assembly couln't be installed:\n" + result);
            }
            File.Delete(remotePath);
        }

        public void Uninstall(string assemblyName)
        {
            string result = ExecGacutil(string.Format(@"/u ""{0}""", assemblyName));
        }
    }
}
